library(tidyverse)

library(janitor)    # for data cleaning
Warning: package ‘janitor’ was built under R version 4.0.4

Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
library(readxl)     # for readig excel files
library(visdat)     # for a quick look at data quality
Warning: package ‘visdat’ was built under R version 4.0.4
theme_set(theme_light())

Processing the data

Gardens data

Dataset downloaded from ONS on 5th June 2021. Both gardens space and public parks datasets are the April 2020 versions.

# a convenience function for renaming columns
# I am sure there is a better way to do this!
replace_in_column_name <- function(df, pattern, replacement){
  df %>% 
    rename_with(.fn = ~ str_replace(.x, pattern, replacement))
}

# read in and clean data
gardens <- read_xlsx(
  "data/osprivateoutdoorspacereferencetables_edited_for_import.xlsx",
  sheet = "MSOA gardens", 
  skip = 1) %>% 
  
  # make variables names more conistent
  janitor::clean_names() %>% 
  
  # focus on variables of interest 
  select(country_code:msoa_name,
         ends_with("count") |
         starts_with("total")) %>% 
  
  # simplify variables names (now data by housing type has been removed)
  replace_in_column_name("total_", "") %>% 
  replace_in_column_name("private_outdoor_space", "gar") %>% 
  replace_in_column_name("address", "ad") %>% 
  replace_in_column_name("adress", "ad") %>%
  replace_in_column_name("adresses", "ads") %>% 
  replace_in_column_name("percentage", "perc") %>% 
  replace_in_column_name("_m2", "") %>% 
  replace_in_column_name("average", "ave")

# display data for quick visual checks
gardens
NA
NA
# get a quick visual summary of data types and the amount of missing data
gardens %>% 
  visdat::vis_dat()


gardens %>% 
  visdat::vis_miss()

Indicies of multiple deprivation

ONS released the 2019 IMD data at LSOA scale. MySociety have produced IMD at various other scales including the MSOA scale.

imd_2019 <- read_csv("data/imd2019_msoa_level_data.csv")

-- Column specification ----------------------------------------------------------------------------------------
cols(
  MSOAC = col_character(),
  MSOAHOCLN = col_character(),
  LAD19C = col_character(),
  LAD19N = col_character(),
  REG = col_character(),
  LSOACOUNT = col_double(),
  POPMID15 = col_double(),
  `IMD19 SCORE` = col_double(),
  MSOARANK = col_double(),
  MSOADECILE = col_double(),
  MSOAQUINTILE = col_double()
)
imd_2019

Population data

ONS provide MSOA level population data. Here I use the most recent release (mid 2019).

msoa_pops <- read_xlsx(
  
  "data/SAPE22DT4-mid-2019-msoa-syoa-estimates-unformatted.xlsx",
  sheet = "Mid-2019 Persons",
  skip = 4) %>% 
  
  # process variable names for conistency
  janitor::clean_names() %>% 
  
  # select minimal number of columns
  select(msoa_code, population = all_ages)

msoa_pops %>% 
  visdat::vis_miss()

Transforming the data for plotting

conservative estimate is the the lowest (1.8 mid-rise)

Overall average = 2.4 (2020 see here)

2017-18 was the most year I could find on average occupancy figures broken down by house/flat from MCHLG:

  • House = 2.5 people

  • High-rise flat = 1.9

  • Mid-rise flat = 1.8

More details here.

So for now, I’ll make a conservative assumption that the average occupancy for a flat is 1.8 (i.e. the lower of the mid and high rise figures above).

I looked at trying to estimate more accurately, but the figures for the number of dwellings per block are not available.

2020 estimates of the numbers of high and mid rise flat can be found here. These can be used to calculate an average flat occupancy rate.

  • 12,500 blocks of high rise flats

  • 77,500 blocks of mid rise flats

# calculate scaling factors for ave occupancy in an MSOA
# from national data
nat_ave_occ <- 2.4
nat_house_ave_occ <- 2.5
nat_flat_ave_occ <- 1.9

flat_scale <- nat_flat_ave_occ / nat_ave_occ
house_scale <- nat_house_ave_occ / nat_ave_occ


people_wo_gar <- gardens %>% 
  left_join(msoa_pops) %>% 
  mutate(house_ad_without_gar_count = houses_ad_count - houses_ad_with_gar_count,
         flats_ad_without_gar_count = flats_ad_count - flats_ad_with_gar_count,
         ave_occ = population / ad_count,
         ave_occ_flat = flat_scale * ave_occ,
         ave_occ_house = house_scale * ave_occ,
         pop_calc = (ave_occ_flat * flats_ad_count) + (ave_occ_house * houses_ad_count),
         pop_diff = population - pop_calc) 
Joining, by = "msoa_code"
ggplot(people_wo_gar, aes(pop_diff)) +
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Warning: Removed 1282 rows containing non-finite values (stat_bin).

NA

May be more accurate to just use average occupancy rates for each MSOA??

people_wo_gar <- gardens %>% 
  left_join(msoa_pops) %>% 
  mutate(ad_wo_gar = ad_count * (1 - perc_of_ades_with_gar),
         ave_occ = population / ad_count,
         people_wo_gar = round(ad_wo_gar * ave_occ)) %>% 
  select(country_code:msoa_name, people_wo_gar)
Joining, by = "msoa_code"
people_wo_gar

ggplot(people_wo_gar, aes(people_wo_gar)) +
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Warning: Removed 1282 rows containing non-finite values (stat_bin).

https://www.robert-hickman.eu/post/getis-ord-heatmaps-tutorial/

library(sf)
Warning: package ‘sf’ was built under R version 4.0.5
Linking to GEOS 3.9.0, GDAL 3.2.1, PROJ 7.2.1
# focus on Englnad and Wales
# (as shapefile for MSOAs only inlcudes England and Wales)
people_wo_gar_EW <- people_wo_gar %>% 
  filter(country_name == "England" |
         country_name == "Wales")

median_msoa_peop_wo_gar = median(people_wo_gar_EW$people_wo_gar, na.rm = TRUE)


# read in MSOA boundary shapefile
msoa_bound <- st_read("data/MSOA_bound/Middle_Layer_Super_Output_Areas_(December_2011)_Boundaries.shp") %>% 
  select(msoa_code = msoa11cd, 
         msoa_name = msoa11nm)
Reading layer `Middle_Layer_Super_Output_Areas_(December_2011)_Boundaries' from data source `C:\Users\chris\Desktop\Data Analysis Projects\green_space\data\MSOA_bound\Middle_Layer_Super_Output_Areas_(December_2011)_Boundaries.shp' using driver `ESRI Shapefile'
Simple feature collection with 7201 features and 6 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 82678 ymin: 5343 xmax: 655604.7 ymax: 657534.1
Projected CRS: OSGB 1936 / British National Grid
# read in countries boundary shapefile (for clipping polygon grid)
country_bound <- st_read("data/Countries_bound/Countries_(December_2017)_Boundaries.shp") %>% 
  filter(ctry17nm == "England" | ctry17nm == "Wales")
Reading layer `Countries_(December_2017)_Boundaries' from data source `C:\Users\chris\Desktop\Data Analysis Projects\green_space\data\Countries_bound\Countries_(December_2017)_Boundaries.shp' using driver `ESRI Shapefile'
Simple feature collection with 3 features and 10 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 5512.999 ymin: 5351.297 xmax: 655644.8 ymax: 1220302
Projected CRS: OSGB 1936 / British National Grid
# join garden data with
people_wo_gar_spatial <- msoa_bound %>% 
  left_join(people_wo_gar_EW) %>% 
  
  # median imputation for one msoa with missing
  mutate(people_wo_gar = replace_na(people_wo_gar, median_msoa_peop_wo_gar))
Joining, by = c("msoa_code", "msoa_name")
  


# ###########################
# simulate the locations of people without a garden
# ###########################

# random locations withi an MSOA was too computationally intesnive
# so I went with placing the 'people' at MSOA centroids
people <- people_wo_gar_spatial %>% 
  mutate(people_wo_gar = round(people_wo_gar / 10),
         geometry = st_centroid(geometry)) %>% 
  uncount(people_wo_gar)


sum(people_wo_gar_spatial$people_wo_gar)
[1] 6702350
# create boundary file
map_bound <- people_wo_gar_spatial %>%
  summarise()# %>% 
  #st_transform(4326)

# people <- st_sample(
#   select(people_wo_gar_spatial, -people_wo_gar),
#   size = round(people_wo_gar_spatial$people_wo_gar / 100))

# ###########################
# create hexagonal grid
# ###########################

hex_polygons <- st_make_grid(map_bound, 7500,
                             crs = st_crs(people_wo_gar_spatial),
                             what = "polygons",
                             square = FALSE) %>% 
  st_sf()

# calculate number of people in each polygon
intersects <- st_intersects(hex_polygons, people)
hex_polygons$people_wo_gar <- lengths(intersects)

# ###########################
# create the plot
# ###########################
# ggplot(people_wo_gar_spatial) +
#   #geom_sf(data = map_bound, colour = "black", size = 1) +
#   geom_sf(data = hex_polygons, fill = "black") + # , aes(fill = people_wo_gar)
#   scale_fill_viridis_c(trans = "log", direction = -1) +
#   #scale_color_viridis_c(trans = "log") +
#   ggthemes::theme_map()

# crop hexogens to outline of England and Wales
hex_polygons_EW <- hex_polygons[country_bound, ]

# hex_polygon_EW %>% 
#   count(people_wo_gar)

ggplot() +
  #geom_sf(data = map_bound) +
  #geom_sf(data = st_centroid(msoa_bound), colour = "grey") +
  geom_sf(data = hex_polygons_EW, alpha = 0.5, mapping = aes(fill = people_wo_gar)) +
  scale_fill_viridis_c(trans = "log", direction = -1) +
  theme_void()
Warning: Transformation introduced infinite values in discrete y-axis

  
# hex_polygons %>% 
#   filter(people_wo_gar == 0)
# 
# people_wo_gar_spatial %>% 
#   filter(people_wo_gar == 0)

# ###########################
# Smooth
# ###########################

https://pudding.cool/process/regional_smoothing/

ggsave("garden_plot.svg")
Saving 7 x 7 in image
Don't know how to automatically pick scale for object of type localG. Defaulting to continuous.

Looking at change in park usage (in two periods in 2020) vs garden access.

Usage data from Google via ONS


# read in Google/ONS park usage data
park_useage <- read_xlsx("data/change_in_parks_visits_2020_LA.xlsx", skip = 6) %>%
  
  # apply consistent naming style
  janitor::clean_names() %>% 
  
  # shorten names for readiblity
  rename(perc_ch_parks_spring_lock = percent_change_in_visits_to_and_time_spent_in_parks_during_spring_2020_lockdown,
         perc_ch_park_summer = percent_change_in_visits_to_and_time_spent_in_parks_during_july_and_august_2020,
         lad_code = area_codes,
         lad_name = area_names)

park_useage

# read in urban / rural classification
urb_rur_class <- read_csv("data/Rural_Urban_Classification_(2001)_for_MSOAs_in_England_and_Wales/RUC_MSOA_2001_EW_LU.csv") %>% 
  clean_names() %>% 
  select(lad_code = lad01cd, lad_name = lad01nm, 
         class_name = morphology_name, 
         class_code = morphology_code)

-- Column specification ----------------------------------------------------------------------------------------
cols(
  GOR01CD = col_character(),
  GOR01NM = col_character(),
  CTY01CD = col_logical(),
  CTY01NM = col_logical(),
  LAD01CD = col_character(),
  LAD01NM = col_character(),
  MSOA01CD = col_character(),
  MSOA01NM = col_character(),
  RUC01NM = col_character(),
  RUC01CD = col_double(),
  `Morphology Name` = col_character(),
  `Morphology Code` = col_double(),
  `Context Name` = col_character(),
  `Context Code` = col_double()
)
Warning: 6366 parsing failures.
 row     col           expected       actual                                                                                            file
3599 CTY01CD 1/0/T/F/TRUE/FALSE 09           'data/Rural_Urban_Classification_(2001)_for_MSOAs_in_England_and_Wales/RUC_MSOA_2001_EW_LU.csv'
3599 CTY01NM 1/0/T/F/TRUE/FALSE Bedfordshire 'data/Rural_Urban_Classification_(2001)_for_MSOAs_in_England_and_Wales/RUC_MSOA_2001_EW_LU.csv'
3600 CTY01CD 1/0/T/F/TRUE/FALSE 09           'data/Rural_Urban_Classification_(2001)_for_MSOAs_in_England_and_Wales/RUC_MSOA_2001_EW_LU.csv'
3600 CTY01NM 1/0/T/F/TRUE/FALSE Bedfordshire 'data/Rural_Urban_Classification_(2001)_for_MSOAs_in_England_and_Wales/RUC_MSOA_2001_EW_LU.csv'
3601 CTY01CD 1/0/T/F/TRUE/FALSE 09           'data/Rural_Urban_Classification_(2001)_for_MSOAs_in_England_and_Wales/RUC_MSOA_2001_EW_LU.csv'
.... ....... .................. ............ ...................................................................................... [... truncated]
# process urban / rural classification 
urb_rur_LAD <- urb_rur_class %>% 
  mutate(is_urban = class_code == 1) %>% 
  group_by(lad_name) %>% 
  summarise(n_tot = n(),
            n_urban = sum(is_urban),
            prop_urban = n_urban / n_tot) %>% 
  mutate(is_urban_LAD = prop_urban > 0.75)

# read in LA boundaries
LA_bounds <- st_read("data/LA_bound/Local_Authority_Districts_(December_2019)_Boundaries_UK_BFC.shp") %>% 
  rename(lad_code = lad19cd,
         lad_name = lad19nm )
Reading layer `Local_Authority_Districts_(December_2019)_Boundaries_UK_BFC' from data source `C:\Users\chris\Desktop\Data Analysis Projects\green_space\data\LA_bound\Local_Authority_Districts_(December_2019)_Boundaries_UK_BFC.shp' using driver `ESRI Shapefile'
Simple feature collection with 382 features and 10 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -116.1928 ymin: 5337.901 xmax: 655653.8 ymax: 1220302
Projected CRS: OSGB 1936 / British National Grid
LA_bounds
Simple feature collection with 382 features and 10 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -116.1928 ymin: 5337.901 xmax: 655653.8 ymax: 1220302
Projected CRS: OSGB 1936 / British National Grid
First 10 features:
   objectid  lad_code                    lad_name lad19nmw  bng_e  bng_n     long      lat st_areasha
1         1 E06000001                  Hartlepool     <NA> 447160 531474 -1.27018 54.67614   93712620
2         2 E06000002               Middlesbrough     <NA> 451141 516887 -1.21099 54.54467   53881564
3         3 E06000003        Redcar and Cleveland     <NA> 464361 519597 -1.00608 54.56752  245069509
4         4 E06000004            Stockton-on-Tees     <NA> 444940 518183 -1.30664 54.55691  204932954
5         5 E06000005                  Darlington     <NA> 428029 515648 -1.56835 54.53534  197475689
6         6 E06000006                      Halton     <NA> 354246 382146 -2.68853 53.33424   79084035
7         7 E06000007                  Warrington     <NA> 362744 388456 -2.56167 53.39163  180627984
8         8 E06000008       Blackburn with Darwen     <NA> 369490 422806 -2.46360 53.70080  137022080
9         9 E06000009                   Blackpool     <NA> 332819 436635 -3.02199 53.82164   34870886
10       10 E06000010 Kingston upon Hull, City of     <NA> 511894 431650 -0.30382 53.76920   71583612
   st_lengths                       geometry
1    71011.93 MULTIPOLYGON (((447213.9 53...
2    44481.69 MULTIPOLYGON (((448609.9 52...
3    96703.99 MULTIPOLYGON (((455932.3 52...
4   123408.99 MULTIPOLYGON (((444157 5279...
5   107206.40 MULTIPOLYGON (((423496.6 52...
6    77771.10 MULTIPOLYGON (((358374.7 38...
7   114690.86 MULTIPOLYGON (((367308.2 39...
8    65284.97 MULTIPOLYGON (((369226.3 43...
9    34483.49 MULTIPOLYGON (((332985.7 44...
10   64681.12 MULTIPOLYGON (((510966.6 43...
# aggregate gardens data to LAD scale
gardens_LAD <- gardens %>% 
  mutate(ad_wo_gar = round(ad_count * (1 - perc_of_ades_with_gar))) %>% 
  group_by(lad_code, lad_name) %>% 
  summarise(ad_count = sum(ad_count),
            ad_wo_gar = sum(ad_wo_gar),
            prop_ad_wo_gar = ad_wo_gar / ad_count) 
`summarise()` has grouped output by 'lad_code'. You can override using the `.groups` argument.
# join dat sets
gar_park_use <- park_useage %>% 
  left_join(gardens_LAD) %>% 
  left_join(urb_rur_LAD)
Joining, by = c("lad_code", "lad_name")
Joining, by = "lad_name"
# check for NA created during joining
gar_park_use %>% 
  skimr::skim()
-- Data Summary ------------------------
                           Values    
Name                       Piped data
Number of rows             354       
Number of columns          11        
_______________________              
Column type frequency:               
  character                3         
  logical                  1         
  numeric                  7         
________________________             
Group variables            None      

-- Variable type: character ------------------------------------------------------------------------------------
# A tibble: 3 x 8
  skim_variable       n_missing complete_rate   min   max empty n_unique whitespace
* <chr>                   <int>         <dbl> <int> <int> <int>    <int>      <int>
1 lad_code                    3         0.992     9    52     0      351          0
2 lad_name                    2         0.994     4    35     0      352          0
3 perc_ch_park_summer         2         0.994     1     7     0      336          0

-- Variable type: logical --------------------------------------------------------------------------------------
# A tibble: 1 x 5
  skim_variable n_missing complete_rate  mean count             
* <chr>             <int>         <dbl> <dbl> <chr>             
1 is_urban_LAD         42         0.881 0.583 TRU: 182, FAL: 130

-- Variable type: numeric --------------------------------------------------------------------------------------
# A tibble: 7 x 11
  skim_variable             n_missing complete_rate      mean         sd        p0        p25        p50
* <chr>                         <int>         <dbl>     <dbl>      <dbl>     <dbl>      <dbl>      <dbl>
1 perc_ch_parks_spring_lock         2         0.994    13.0      29.3     -82.1       -5.85      13.0   
2 ad_count                          4         0.989 79260.    52299.     7707      45916.     63185     
3 ad_wo_gar                         4         0.989  9292.     9560.     1748       3984.      6249     
4 prop_ad_wo_gar                    4         0.989     0.110     0.0658    0.0349     0.0787     0.0979
5 n_tot                            42         0.881    20.6      13.3       1         13         17     
6 n_urban                          42         0.881    17.0      14.5       0          8         13     
7 prop_urban                       42         0.881     0.754     0.268     0          0.587      0.845 
        p75       p100 hist 
*     <dbl>      <dbl> <chr>
1    29.9      139.    ▁▆▇▁▁
2 98078.    447437     ▇▂▁▁▁
3 10019      62972     ▇▁▁▁▁
4     0.122      0.928 ▇▁▁▁▁
5    25        131     ▇▂▁▁▁
6    23        131     ▇▂▁▁▁
7     1          1     ▁▂▂▃▇
gar_park_use %>% 
  filter(is.na(is_urban_LAD))

# produce plot
ggplot(gar_park_use, aes(prop_ad_wo_gar, perc_ch_parks_spring_lock,
                         colour = is_urban_LAD)) +
  geom_point() +
  geom_smooth(method = "lm") +
  #scale_x_log10() +
  xlim(c(0,0.5)) +
  facet_wrap(~is_urban_LAD)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 5 rows containing non-finite values (stat_smooth).
Warning: Removed 5 rows containing missing values (geom_point).

ggplot(gar_park_use, aes(prop_ad_wo_gar, perc_ch_park_summer)) +
  geom_point()
Warning: Removed 4 rows containing missing values (geom_point).

mod_1 <- rstanarm::stan_glm(perc_ch_parks_spring_lock ~ prop_ad_wo_gar, 
                            data = filter(gar_park_use, 
                                          prop_ad_wo_gar < 0.2 &
                                            is_urban_LAD == TRUE), 
                            refresh = 0)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
median(rstanarm::bayes_R2(mod_1))
[1] 0.1445503
foe_green_space <- read_xlsx("data/(FOE) Green Space Consolidated Data - England - Version 2.1.xlsx",
                             sheet = "Local Authorities V2.1") %>% 
  clean_names() %>% 
  select(lad_code = la_code, 
         lad_name = la_name,
         pop = total_pop_from_ethnicity_data,
         bame_pop,
         income_index,
         pcnt_pop_with_go_space_access,
         green_space_area_per_capita)
New names:
* `` -> ...1
# join foe data to existing data
gar_park_use_foe <- gar_park_use %>% 
  left_join(foe_green_space)
Joining, by = c("lad_code", "lad_name")
# check NAs created by joining
skimr::skim(gar_park_use_foe)
-- Data Summary ------------------------
                           Values          
Name                       gar_park_use_foe
Number of rows             354             
Number of columns          16              
_______________________                    
Column type frequency:                     
  character                3               
  logical                  1               
  numeric                  12              
________________________                   
Group variables            None            

-- Variable type: character ------------------------------------------------------------------------------------
# A tibble: 3 x 8
  skim_variable       n_missing complete_rate   min   max empty n_unique whitespace
* <chr>                   <int>         <dbl> <int> <int> <int>    <int>      <int>
1 lad_code                    3         0.992     9    52     0      351          0
2 lad_name                    2         0.994     4    35     0      352          0
3 perc_ch_park_summer         2         0.994     1     7     0      336          0

-- Variable type: logical --------------------------------------------------------------------------------------
# A tibble: 1 x 5
  skim_variable n_missing complete_rate  mean count             
* <chr>             <int>         <dbl> <dbl> <chr>             
1 is_urban_LAD         42         0.881 0.583 TRU: 182, FAL: 130

-- Variable type: numeric --------------------------------------------------------------------------------------
# A tibble: 12 x 11
   skim_variable                 n_missing complete_rate       mean          sd        p0        p25         p50
 * <chr>                             <int>         <dbl>      <dbl>       <dbl>     <dbl>      <dbl>       <dbl>
 1 perc_ch_parks_spring_lock             2         0.994     13.0       29.3     -82.1       -5.85       13.0   
 2 ad_count                              4         0.989  79260.     52299.     7707      45916.      63185     
 3 ad_wo_gar                             4         0.989   9292.      9560.     1748       3984.       6249     
 4 prop_ad_wo_gar                        4         0.989      0.110      0.0658    0.0349     0.0787      0.0979
 5 n_tot                                42         0.881     20.6       13.3       1         13          17     
 6 n_urban                              42         0.881     17.0       14.5       0          8          13     
 7 prop_urban                           42         0.881      0.754      0.268     0          0.587       0.845 
 8 pop                                  52         0.853 169400.    114457.     7375      97389.     132484.    
 9 bame_pop                             52         0.853  25213.     46089.      565       3308.       7918     
10 income_index                         52         0.853      5.81       1.46      2.79       4.67        5.81  
11 pcnt_pop_with_go_space_access        52         0.853     33.0       11.7       7.48      24.2        33.8   
12 green_space_area_per_capita          52         0.853    348.      1405.        2.36      25.5        46.7   
          p75        p100 hist 
 *      <dbl>       <dbl> <chr>
 1     29.9       139.    ▁▆▇▁▁
 2  98078.     447437     ▇▂▁▁▁
 3  10019       62972     ▇▁▁▁▁
 4      0.122       0.928 ▇▁▁▁▁
 5     25         131     ▇▂▁▁▁
 6     23         131     ▇▂▁▁▁
 7      1           1     ▁▂▂▃▇
 8 211063.    1073045     ▇▂▁▁▁
 9  21377.     451409     ▇▁▁▁▁
10      7.02        9.01  ▃▆▇▆▃
11     41.0        75.2   ▃▇▇▂▁
12    111.      16646.    ▇▁▁▁▁
gar_park_use_foe %>% 
  filter(is.na(pop))  # almost all Scotland and Wales 
                      # (as expected as FOE is England only)


gar_park_use_foe_eng <- gar_park_use_foe %>% 
  filter(!is.na(pop)) %>% 
  mutate(perc_ch_park_summer = na_if(perc_ch_park_summer, "No data"),
         perc_ch_park_summer = as.numeric(perc_ch_park_summer),
         prop_bame_pop = bame_pop / pop)

gar_park_use_foe_eng

gar_park_use_foe_eng_mod_in <- gar_park_use_foe_eng %>% 
  select(-lad_code, -lad_name, -pop, -bame_pop,
         -n_tot, -n_urban, -is_urban_LAD, -ad_count,-ad_wo_gar,
         -perc_ch_park_summer, -pcnt_pop_with_go_space_access, -green_space_area_per_capita)
  

mod_2 <- rstanarm::stan_glm(perc_ch_parks_spring_lock ~ ., 
                            data = gar_park_use_foe_eng_mod_in, 
                            refresh = 0)

median(rstanarm::bayes_R2(mod_2))
[1] 0.1692073
mod_3 <- rstanarm::stan_glm(perc_ch_parks_spring_lock ~ prop_ad_wo_gar + prop_urban + income_index + prop_bame_pop, 
                            data = gar_park_use_foe_eng_mod_in, 
                            refresh = 0)

median(rstanarm::bayes_R2(mod_3))
[1] 0.1692193
ggplot(gar_park_use_foe_eng_mod_in, aes(prop_bame_pop, perc_ch_parks_spring_lock)) +
  geom_point()


p <- ggplot(filter(gar_park_use_foe_eng, prop_urban > 0.8), 
       aes(prop_ad_wo_gar, perc_ch_parks_spring_lock, 
           colour = prop_bame_pop, 
           size = green_space_area_per_capita,
           label = lad_name)) +
  geom_point(alpha = 0.5) +
  scale_colour_viridis_c() +
  xlim(c(0,.5))
  #scale_x_log10()

plotly::ggplotly(p)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
p2 <- ggplot(data = filter(gar_park_use_foe_eng, prop_urban > 0.8),
             aes(prop_bame_pop, prop_ad_wo_gar)) +
  geom_point() +
  ylim(c(0,0.5))

p2
Warning: Removed 1 rows containing missing values (geom_point).

p3 <- ggplot(filter(gar_park_use_foe_eng, prop_urban > 0.8), 
       aes(prop_bame_pop, perc_ch_parks_spring_lock, 
           colour = prop_ad_wo_gar, 
           size = green_space_area_per_capita,
           label = lad_name)) +
  geom_point(alpha = 0.5) +
  scale_colour_viridis_c(direction = -1, trans = "log", end = 0.9) +
  xlim(c(0,.5))

p3
Warning: Removed 7 rows containing missing values (geom_point).

plotly::ggplotly(p3)

p4 <- ggplot(filter(gar_park_use_foe_eng, prop_urban > 0.8), 
       aes(perc_ch_parks_spring_lock, perc_ch_park_summer,
           colour = prop_ad_wo_gar,
           size = green_space_area_per_capita,
           label = lad_name)) +
  geom_point(alpha = 0.5)+
  scale_colour_viridis_c(direction = -1, trans = "log", end = 0.9)

p4
Warning: Removed 7 rows containing missing values (geom_point).

plotly::ggplotly(p4)

Major cities

la_region_lookup <- gardens %>%
  select(region_code:lad_name) %>% 
  distinct()

london <- gar_park_use_foe_eng %>% 
  left_join(la_region_lookup) %>% 
  filter(region_name == "London")
Joining, by = c("lad_code", "lad_name")
other_big_cities <- gar_park_use_foe_eng %>% 
  left_join(la_region_lookup) %>% 
  filter(region_name != "London") %>% 
  filter(prop_urban >= 0.8) %>% 
  slice_max(order_by = pop, n = 29)
Joining, by = c("lad_code", "lad_name")
thirty_biggest_cities <- london %>% 
  bind_rows(other_big_cities) %>% 
  mutate(is_london = region_name == "London",
         gs_pc_bin = cut(green_space_area_per_capita,
                         breaks = c(0, 10, 25, 50, Inf)),
         prop_ad_with_gar = 1 - prop_ad_wo_gar)

colours <- c("grey30", "grey70", "palegreen", "palegreen4")

p <- ggplot(thirty_biggest_cities, 
       aes(prop_ad_with_gar, perc_ch_parks_spring_lock, 
           colour = gs_pc_bin, 
           size = gs_pc_bin,
           label = lad_name)) +
  geom_point(alpha = 0.5) +
  scale_colour_manual(values = colours) +
  #scale_colour_viridis_c() +
  #scale_colour_gradient(low = "grey30", high = "green") +
  xlim(c(0.5,1)) +
  facet_wrap(~is_london)
  #scale_x_log10()

plotly::ggplotly(p)
Warning: Using size for a discrete variable is not advised.
ggplot(thirty_biggest_cities) +
  geom_histogram(mapping = aes(green_space_area_per_capita))
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

p4 <- ggplot(thirty_biggest_cities, 
       aes(perc_ch_parks_spring_lock, perc_ch_park_summer,
           colour = green_space_area_per_capita,
           size = green_space_area_per_capita,
           label = lad_name)) +
  geom_point(alpha = 0.5)+
  scale_colour_viridis_c(end = 0.9) +
  facet_wrap(~is_london)

p4


plotly::ggplotly(p4)
LA_bounds
Simple feature collection with 382 features and 10 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -116.1928 ymin: 5337.901 xmax: 655653.8 ymax: 1220302
Projected CRS: OSGB 1936 / British National Grid
First 10 features:
   objectid   lad19cd                     lad19nm lad19nmw  bng_e  bng_n     long      lat st_areasha
1         1 E06000001                  Hartlepool     <NA> 447160 531474 -1.27018 54.67614   93712620
2         2 E06000002               Middlesbrough     <NA> 451141 516887 -1.21099 54.54467   53881564
3         3 E06000003        Redcar and Cleveland     <NA> 464361 519597 -1.00608 54.56752  245069509
4         4 E06000004            Stockton-on-Tees     <NA> 444940 518183 -1.30664 54.55691  204932954
5         5 E06000005                  Darlington     <NA> 428029 515648 -1.56835 54.53534  197475689
6         6 E06000006                      Halton     <NA> 354246 382146 -2.68853 53.33424   79084035
7         7 E06000007                  Warrington     <NA> 362744 388456 -2.56167 53.39163  180627984
8         8 E06000008       Blackburn with Darwen     <NA> 369490 422806 -2.46360 53.70080  137022080
9         9 E06000009                   Blackpool     <NA> 332819 436635 -3.02199 53.82164   34870886
10       10 E06000010 Kingston upon Hull, City of     <NA> 511894 431650 -0.30382 53.76920   71583612
   st_lengths                       geometry
1    71011.93 MULTIPOLYGON (((447213.9 53...
2    44481.69 MULTIPOLYGON (((448609.9 52...
3    96703.99 MULTIPOLYGON (((455932.3 52...
4   123408.99 MULTIPOLYGON (((444157 5279...
5   107206.40 MULTIPOLYGON (((423496.6 52...
6    77771.10 MULTIPOLYGON (((358374.7 38...
7   114690.86 MULTIPOLYGON (((367308.2 39...
8    65284.97 MULTIPOLYGON (((369226.3 43...
9    34483.49 MULTIPOLYGON (((332985.7 44...
10   64681.12 MULTIPOLYGON (((510966.6 43...
LS0tDQp0aXRsZTogIkVzdGltYXRpbmcgdGhlIG51bWJlciBvZiBwZW9wbGUgd2l0aG91dCBhIGdhcmRlbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCmxpYnJhcnkoamFuaXRvcikgICAgIyBmb3IgZGF0YSBjbGVhbmluZw0KbGlicmFyeShyZWFkeGwpICAgICAjIGZvciByZWFkaWcgZXhjZWwgZmlsZXMNCmxpYnJhcnkodmlzZGF0KSAgICAgIyBmb3IgYSBxdWljayBsb29rIGF0IGRhdGEgcXVhbGl0eQ0KYGBgDQoNCmBgYHtyfQ0KdGhlbWVfc2V0KHRoZW1lX2xpZ2h0KCkpDQpgYGANCg0KIyMgUHJvY2Vzc2luZyB0aGUgZGF0YQ0KDQojIyMgR2FyZGVucyBkYXRhDQoNCkRhdGFzZXQgZG93bmxvYWRlZCBmcm9tIFtPTlNdKGh0dHBzOi8vd3d3Lm9ucy5nb3YudWsvZWNvbm9teS9lbnZpcm9ubWVudGFsYWNjb3VudHMvZGF0YXNldHMvYWNjZXNzdG9nYXJkZW5zYW5kcHVibGljZ3JlZW5zcGFjZWluZ3JlYXRicml0YWluKSBvbiA1dGggSnVuZSAyMDIxLiBCb3RoIGdhcmRlbnMgc3BhY2UgYW5kIHB1YmxpYyBwYXJrcyBkYXRhc2V0cyBhcmUgdGhlIEFwcmlsIDIwMjAgdmVyc2lvbnMuDQoNCmBgYHtyfQ0KIyBhIGNvbnZlbmllbmNlIGZ1bmN0aW9uIGZvciByZW5hbWluZyBjb2x1bW5zDQojIEkgYW0gc3VyZSB0aGVyZSBpcyBhIGJldHRlciB3YXkgdG8gZG8gdGhpcyENCnJlcGxhY2VfaW5fY29sdW1uX25hbWUgPC0gZnVuY3Rpb24oZGYsIHBhdHRlcm4sIHJlcGxhY2VtZW50KXsNCiAgZGYgJT4lIA0KICAgIHJlbmFtZV93aXRoKC5mbiA9IH4gc3RyX3JlcGxhY2UoLngsIHBhdHRlcm4sIHJlcGxhY2VtZW50KSkNCn0NCg0KIyByZWFkIGluIGFuZCBjbGVhbiBkYXRhDQpnYXJkZW5zIDwtIHJlYWRfeGxzeCgNCiAgImRhdGEvb3Nwcml2YXRlb3V0ZG9vcnNwYWNlcmVmZXJlbmNldGFibGVzX2VkaXRlZF9mb3JfaW1wb3J0Lnhsc3giLA0KICBzaGVldCA9ICJNU09BIGdhcmRlbnMiLCANCiAgc2tpcCA9IDEpICU+JSANCiAgDQogICMgbWFrZSB2YXJpYWJsZXMgbmFtZXMgbW9yZSBjb25pc3RlbnQNCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIA0KICAjIGZvY3VzIG9uIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCANCiAgc2VsZWN0KGNvdW50cnlfY29kZTptc29hX25hbWUsDQogICAgICAgICBlbmRzX3dpdGgoImNvdW50IikgfA0KICAgICAgICAgc3RhcnRzX3dpdGgoInRvdGFsIikpICU+JSANCiAgDQogICMgc2ltcGxpZnkgdmFyaWFibGVzIG5hbWVzIChub3cgZGF0YSBieSBob3VzaW5nIHR5cGUgaGFzIGJlZW4gcmVtb3ZlZCkNCiAgcmVwbGFjZV9pbl9jb2x1bW5fbmFtZSgidG90YWxfIiwgIiIpICU+JSANCiAgcmVwbGFjZV9pbl9jb2x1bW5fbmFtZSgicHJpdmF0ZV9vdXRkb29yX3NwYWNlIiwgImdhciIpICU+JSANCiAgcmVwbGFjZV9pbl9jb2x1bW5fbmFtZSgiYWRkcmVzcyIsICJhZCIpICU+JSANCiAgcmVwbGFjZV9pbl9jb2x1bW5fbmFtZSgiYWRyZXNzIiwgImFkIikgJT4lDQogIHJlcGxhY2VfaW5fY29sdW1uX25hbWUoImFkcmVzc2VzIiwgImFkcyIpICU+JSANCiAgcmVwbGFjZV9pbl9jb2x1bW5fbmFtZSgicGVyY2VudGFnZSIsICJwZXJjIikgJT4lIA0KICByZXBsYWNlX2luX2NvbHVtbl9uYW1lKCJfbTIiLCAiIikgJT4lIA0KICByZXBsYWNlX2luX2NvbHVtbl9uYW1lKCJhdmVyYWdlIiwgImF2ZSIpDQoNCiMgZGlzcGxheSBkYXRhIGZvciBxdWljayB2aXN1YWwgY2hlY2tzDQpnYXJkZW5zDQogIA0KICANCmBgYA0KDQpgYGB7cn0NCiMgZ2V0IGEgcXVpY2sgdmlzdWFsIHN1bW1hcnkgb2YgZGF0YSB0eXBlcyBhbmQgdGhlIGFtb3VudCBvZiBtaXNzaW5nIGRhdGENCmdhcmRlbnMgJT4lIA0KICB2aXNkYXQ6OnZpc19kYXQoKQ0KDQpnYXJkZW5zICU+JSANCiAgdmlzZGF0Ojp2aXNfbWlzcygpDQpgYGANCg0KIyMjIEluZGljaWVzIG9mIG11bHRpcGxlIGRlcHJpdmF0aW9uDQoNCk9OUyByZWxlYXNlZCB0aGUgMjAxOSBJTUQgZGF0YSBhdCBMU09BIHNjYWxlLiBNeVNvY2lldHkgaGF2ZSBwcm9kdWNlZCBbSU1EIGF0IHZhcmlvdXMgb3RoZXIgc2NhbGVzXShodHRwczovL3Jlc2VhcmNoLm15c29jaWV0eS5vcmcvc2l0ZXMvaW1kMjAxOS9hYm91dC8pIGluY2x1ZGluZyB0aGUgTVNPQSBzY2FsZS4NCg0KYGBge3J9DQppbWRfMjAxOSA8LSByZWFkX2NzdigiZGF0YS9pbWQyMDE5X21zb2FfbGV2ZWxfZGF0YS5jc3YiKQ0KaW1kXzIwMTkNCmBgYA0KDQojIyMgUG9wdWxhdGlvbiBkYXRhDQoNCk9OUyBwcm92aWRlIFtNU09BIGxldmVsIHBvcHVsYXRpb24gZGF0YV0oaHR0cHM6Ly93d3cub25zLmdvdi51ay9wZW9wbGVwb3B1bGF0aW9uYW5kY29tbXVuaXR5L3BvcHVsYXRpb25hbmRtaWdyYXRpb24vcG9wdWxhdGlvbmVzdGltYXRlcy9kYXRhc2V0cy9taWRkbGVzdXBlcm91dHB1dGFyZWFtaWR5ZWFycG9wdWxhdGlvbmVzdGltYXRlcykuIEhlcmUgSSB1c2UgdGhlIG1vc3QgcmVjZW50IHJlbGVhc2UgKG1pZCAyMDE5KS4NCg0KYGBge3J9DQptc29hX3BvcHMgPC0gcmVhZF94bHN4KA0KICANCiAgImRhdGEvU0FQRTIyRFQ0LW1pZC0yMDE5LW1zb2Etc3lvYS1lc3RpbWF0ZXMtdW5mb3JtYXR0ZWQueGxzeCIsDQogIHNoZWV0ID0gIk1pZC0yMDE5IFBlcnNvbnMiLA0KICBza2lwID0gNCkgJT4lIA0KICANCiAgIyBwcm9jZXNzIHZhcmlhYmxlIG5hbWVzIGZvciBjb25pc3RlbmN5DQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lIA0KICANCiAgIyBzZWxlY3QgbWluaW1hbCBudW1iZXIgb2YgY29sdW1ucw0KICBzZWxlY3QobXNvYV9jb2RlLCBwb3B1bGF0aW9uID0gYWxsX2FnZXMpDQoNCm1zb2FfcG9wcyAlPiUgDQogIHZpc2RhdDo6dmlzX21pc3MoKQ0KYGBgDQoNCiMjIyBUcmFuc2Zvcm1pbmcgdGhlIGRhdGEgZm9yIHBsb3R0aW5nDQoNCmNvbnNlcnZhdGl2ZSBlc3RpbWF0ZSBpcyB0aGUgdGhlIGxvd2VzdCAoMS44IG1pZC1yaXNlKQ0KDQpPdmVyYWxsIGF2ZXJhZ2UgPSAyLjQgKDIwMjAgc2VlIFtoZXJlXShodHRwczovL3d3dy5vbnMuZ292LnVrL3Blb3BsZXBvcHVsYXRpb25hbmRjb21tdW5pdHkvYmlydGhzZGVhdGhzYW5kbWFycmlhZ2VzL2ZhbWlsaWVzL2J1bGxldGlucy9mYW1pbGllc2FuZGhvdXNlaG9sZHMvMjAyMCkpDQoNCjIwMTctMTggd2FzIHRoZSBtb3N0IHllYXIgSSBjb3VsZCBmaW5kIG9uIFthdmVyYWdlIG9jY3VwYW5jeSBmaWd1cmVzIGJyb2tlbiBkb3duIGJ5IGhvdXNlL2ZsYXQgZnJvbSBNQ0hMR10oaHR0cHM6Ly9hc3NldHMucHVibGlzaGluZy5zZXJ2aWNlLmdvdi51ay9nb3Zlcm5tZW50L3VwbG9hZHMvc3lzdGVtL3VwbG9hZHMvYXR0YWNobWVudF9kYXRhL2ZpbGUvODE3Mjg2L0VIU18yMDE3LTE4X0hvdXNlaG9sZHNfUmVwb3J0LnBkZik6DQoNCi0gICBIb3VzZSA9IDIuNSBwZW9wbGUNCg0KLSAgIEhpZ2gtcmlzZSBmbGF0ID0gMS45DQoNCi0gICBNaWQtcmlzZSBmbGF0ID0gMS44DQoNCk1vcmUgZGV0YWlscyBbaGVyZV0oaHR0cHM6Ly93d3cuZ292LnVrL2dvdmVybm1lbnQvc3RhdGlzdGljcy9lbmdsaXNoLWhvdXNpbmctc3VydmV5LTIwMTctdG8tMjAxOC1ob3VzZWhvbGRzKS4NCg0KU28gZm9yIG5vdywgSSdsbCBtYWtlIGEgY29uc2VydmF0aXZlIGFzc3VtcHRpb24gdGhhdCB0aGUgYXZlcmFnZSBvY2N1cGFuY3kgZm9yIGEgZmxhdCBpcyAxLjggKGkuZS4gdGhlIGxvd2VyIG9mIHRoZSBtaWQgYW5kIGhpZ2ggcmlzZSBmaWd1cmVzIGFib3ZlKS4NCg0KKipJIGxvb2tlZCBhdCB0cnlpbmcgdG8gZXN0aW1hdGUgbW9yZSBhY2N1cmF0ZWx5LCBidXQgdGhlIGZpZ3VyZXMgZm9yIHRoZSBudW1iZXIgb2YgZHdlbGxpbmdzIHBlciBibG9jayBhcmUgbm90IGF2YWlsYWJsZS4qKg0KDQoyMDIwIGVzdGltYXRlcyBvZiB0aGUgbnVtYmVycyBvZiBoaWdoIGFuZCBtaWQgcmlzZSBmbGF0IGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly93d3cuZ292LnVrL2dvdmVybm1lbnQvcHVibGljYXRpb25zL2J1aWxkaW5nLXNhZmV0eS1wcm9ncmFtbWUtZXN0aW1hdGVzLW9mLWV3czEtcmVxdWlyZW1lbnRzLW9uLXJlc2lkZW50aWFsLWJ1aWxkaW5ncy1pbi1lbmdsYW5kL2J1aWxkaW5nLXNhZmV0eS1wcm9ncmFtbWUtZXN0aW1hdGVzLW9mLWV3czEtcmVxdWlyZW1lbnRzLW9uLXJlc2lkZW50aWFsLWJ1aWxkaW5ncy1pbi1lbmdsYW5kKS4gVGhlc2UgY2FuIGJlIHVzZWQgdG8gY2FsY3VsYXRlIGFuIGF2ZXJhZ2UgZmxhdCBvY2N1cGFuY3kgcmF0ZS4NCg0KLSAgIDEyLDUwMCBibG9ja3Mgb2YgaGlnaCByaXNlIGZsYXRzDQoNCi0gICA3Nyw1MDAgYmxvY2tzIG9mIG1pZCByaXNlIGZsYXRzDQoNCmBgYHtyfQ0KIyBjYWxjdWxhdGUgc2NhbGluZyBmYWN0b3JzIGZvciBhdmUgb2NjdXBhbmN5IGluIGFuIE1TT0ENCiMgZnJvbSBuYXRpb25hbCBkYXRhDQpuYXRfYXZlX29jYyA8LSAyLjQNCm5hdF9ob3VzZV9hdmVfb2NjIDwtIDIuNQ0KbmF0X2ZsYXRfYXZlX29jYyA8LSAxLjkNCg0KZmxhdF9zY2FsZSA8LSBuYXRfZmxhdF9hdmVfb2NjIC8gbmF0X2F2ZV9vY2MNCmhvdXNlX3NjYWxlIDwtIG5hdF9ob3VzZV9hdmVfb2NjIC8gbmF0X2F2ZV9vY2MNCg0KDQpwZW9wbGVfd29fZ2FyIDwtIGdhcmRlbnMgJT4lIA0KICBsZWZ0X2pvaW4obXNvYV9wb3BzKSAlPiUgDQogIG11dGF0ZShob3VzZV9hZF93aXRob3V0X2dhcl9jb3VudCA9IGhvdXNlc19hZF9jb3VudCAtIGhvdXNlc19hZF93aXRoX2dhcl9jb3VudCwNCiAgICAgICAgIGZsYXRzX2FkX3dpdGhvdXRfZ2FyX2NvdW50ID0gZmxhdHNfYWRfY291bnQgLSBmbGF0c19hZF93aXRoX2dhcl9jb3VudCwNCiAgICAgICAgIGF2ZV9vY2MgPSBwb3B1bGF0aW9uIC8gYWRfY291bnQsDQogICAgICAgICBhdmVfb2NjX2ZsYXQgPSBmbGF0X3NjYWxlICogYXZlX29jYywNCiAgICAgICAgIGF2ZV9vY2NfaG91c2UgPSBob3VzZV9zY2FsZSAqIGF2ZV9vY2MsDQogICAgICAgICBwb3BfY2FsYyA9IChhdmVfb2NjX2ZsYXQgKiBmbGF0c19hZF9jb3VudCkgKyAoYXZlX29jY19ob3VzZSAqIGhvdXNlc19hZF9jb3VudCksDQogICAgICAgICBwb3BfZGlmZiA9IHBvcHVsYXRpb24gLSBwb3BfY2FsYykgDQoNCmdncGxvdChwZW9wbGVfd29fZ2FyLCBhZXMocG9wX2RpZmYpKSArDQogIGdlb21faGlzdG9ncmFtKCkNCiAgDQpgYGANCg0KTWF5IGJlIG1vcmUgYWNjdXJhdGUgdG8ganVzdCB1c2UgYXZlcmFnZSBvY2N1cGFuY3kgcmF0ZXMgZm9yIGVhY2ggTVNPQT8/DQoNCmBgYHtyfQ0KcGVvcGxlX3dvX2dhciA8LSBnYXJkZW5zICU+JSANCiAgbGVmdF9qb2luKG1zb2FfcG9wcykgJT4lIA0KICBtdXRhdGUoYWRfd29fZ2FyID0gYWRfY291bnQgKiAoMSAtIHBlcmNfb2ZfYWRlc193aXRoX2dhciksDQogICAgICAgICBhdmVfb2NjID0gcG9wdWxhdGlvbiAvIGFkX2NvdW50LA0KICAgICAgICAgcGVvcGxlX3dvX2dhciA9IHJvdW5kKGFkX3dvX2dhciAqIGF2ZV9vY2MpKSAlPiUgDQogIHNlbGVjdChjb3VudHJ5X2NvZGU6bXNvYV9uYW1lLCBwZW9wbGVfd29fZ2FyKQ0KDQpwZW9wbGVfd29fZ2FyDQoNCmdncGxvdChwZW9wbGVfd29fZ2FyLCBhZXMocGVvcGxlX3dvX2dhcikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oKQ0KDQpgYGANCg0KPGh0dHBzOi8vd3d3LnJvYmVydC1oaWNrbWFuLmV1L3Bvc3QvZ2V0aXMtb3JkLWhlYXRtYXBzLXR1dG9yaWFsLz4NCg0KYGBge3J9DQpsaWJyYXJ5KHNmKQ0KDQojIGZvY3VzIG9uIEVuZ2xuYWQgYW5kIFdhbGVzDQojIChhcyBzaGFwZWZpbGUgZm9yIE1TT0FzIG9ubHkgaW5sY3VkZXMgRW5nbGFuZCBhbmQgV2FsZXMpDQpwZW9wbGVfd29fZ2FyX0VXIDwtIHBlb3BsZV93b19nYXIgJT4lIA0KICBmaWx0ZXIoY291bnRyeV9uYW1lID09ICJFbmdsYW5kIiB8DQogICAgICAgICBjb3VudHJ5X25hbWUgPT0gIldhbGVzIikNCg0KbWVkaWFuX21zb2FfcGVvcF93b19nYXIgPSBtZWRpYW4ocGVvcGxlX3dvX2dhcl9FVyRwZW9wbGVfd29fZ2FyLCBuYS5ybSA9IFRSVUUpDQoNCg0KIyByZWFkIGluIE1TT0EgYm91bmRhcnkgc2hhcGVmaWxlDQptc29hX2JvdW5kIDwtIHN0X3JlYWQoImRhdGEvTVNPQV9ib3VuZC9NaWRkbGVfTGF5ZXJfU3VwZXJfT3V0cHV0X0FyZWFzXyhEZWNlbWJlcl8yMDExKV9Cb3VuZGFyaWVzLnNocCIpICU+JSANCiAgc2VsZWN0KG1zb2FfY29kZSA9IG1zb2ExMWNkLCANCiAgICAgICAgIG1zb2FfbmFtZSA9IG1zb2ExMW5tKQ0KDQojIHJlYWQgaW4gY291bnRyaWVzIGJvdW5kYXJ5IHNoYXBlZmlsZSAoZm9yIGNsaXBwaW5nIHBvbHlnb24gZ3JpZCkNCmNvdW50cnlfYm91bmQgPC0gc3RfcmVhZCgiZGF0YS9Db3VudHJpZXNfYm91bmQvQ291bnRyaWVzXyhEZWNlbWJlcl8yMDE3KV9Cb3VuZGFyaWVzLnNocCIpICU+JSANCiAgZmlsdGVyKGN0cnkxN25tID09ICJFbmdsYW5kIiB8IGN0cnkxN25tID09ICJXYWxlcyIpDQoNCiMgam9pbiBnYXJkZW4gZGF0YSB3aXRoDQpwZW9wbGVfd29fZ2FyX3NwYXRpYWwgPC0gbXNvYV9ib3VuZCAlPiUgDQogIGxlZnRfam9pbihwZW9wbGVfd29fZ2FyX0VXKSAlPiUgDQogIA0KICAjIG1lZGlhbiBpbXB1dGF0aW9uIGZvciBvbmUgbXNvYSB3aXRoIG1pc3NpbmcNCiAgbXV0YXRlKHBlb3BsZV93b19nYXIgPSByZXBsYWNlX25hKHBlb3BsZV93b19nYXIsIG1lZGlhbl9tc29hX3Blb3Bfd29fZ2FyKSkNCiAgDQoNCg0KIyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgc2ltdWxhdGUgdGhlIGxvY2F0aW9ucyBvZiBwZW9wbGUgd2l0aG91dCBhIGdhcmRlbg0KIyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyByYW5kb20gbG9jYXRpb25zIHdpdGhpIGFuIE1TT0Egd2FzIHRvbyBjb21wdXRhdGlvbmFsbHkgaW50ZXNuaXZlDQojIHNvIEkgd2VudCB3aXRoIHBsYWNpbmcgdGhlICdwZW9wbGUnIGF0IE1TT0EgY2VudHJvaWRzDQpwZW9wbGUgPC0gcGVvcGxlX3dvX2dhcl9zcGF0aWFsICU+JSANCiAgbXV0YXRlKHBlb3BsZV93b19nYXIgPSByb3VuZChwZW9wbGVfd29fZ2FyIC8gMTApLA0KICAgICAgICAgZ2VvbWV0cnkgPSBzdF9jZW50cm9pZChnZW9tZXRyeSkpICU+JSANCiAgdW5jb3VudChwZW9wbGVfd29fZ2FyKQ0KDQoNCnN1bShwZW9wbGVfd29fZ2FyX3NwYXRpYWwkcGVvcGxlX3dvX2dhcikNCiMgY3JlYXRlIGJvdW5kYXJ5IGZpbGUNCm1hcF9ib3VuZCA8LSBwZW9wbGVfd29fZ2FyX3NwYXRpYWwgJT4lDQogIHN1bW1hcmlzZSgpIyAlPiUgDQogICNzdF90cmFuc2Zvcm0oNDMyNikNCg0KIyBwZW9wbGUgPC0gc3Rfc2FtcGxlKA0KIyAgIHNlbGVjdChwZW9wbGVfd29fZ2FyX3NwYXRpYWwsIC1wZW9wbGVfd29fZ2FyKSwNCiMgICBzaXplID0gcm91bmQocGVvcGxlX3dvX2dhcl9zcGF0aWFsJHBlb3BsZV93b19nYXIgLyAxMDApKQ0KDQojICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBjcmVhdGUgaGV4YWdvbmFsIGdyaWQNCiMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCmhleF9wb2x5Z29ucyA8LSBzdF9tYWtlX2dyaWQobWFwX2JvdW5kLCA3NTAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnMgPSBzdF9jcnMocGVvcGxlX3dvX2dhcl9zcGF0aWFsKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hhdCA9ICJwb2x5Z29ucyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNxdWFyZSA9IEZBTFNFKSAlPiUgDQogIHN0X3NmKCkNCg0KIyBjYWxjdWxhdGUgbnVtYmVyIG9mIHBlb3BsZSBpbiBlYWNoIHBvbHlnb24NCmludGVyc2VjdHMgPC0gc3RfaW50ZXJzZWN0cyhoZXhfcG9seWdvbnMsIHBlb3BsZSkNCmhleF9wb2x5Z29ucyRwZW9wbGVfd29fZ2FyIDwtIGxlbmd0aHMoaW50ZXJzZWN0cykNCg0KIyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgY3JlYXRlIHRoZSBwbG90DQojICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBnZ3Bsb3QocGVvcGxlX3dvX2dhcl9zcGF0aWFsKSArDQojICAgI2dlb21fc2YoZGF0YSA9IG1hcF9ib3VuZCwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDEpICsNCiMgICBnZW9tX3NmKGRhdGEgPSBoZXhfcG9seWdvbnMsIGZpbGwgPSAiYmxhY2siKSArICMgLCBhZXMoZmlsbCA9IHBlb3BsZV93b19nYXIpDQojICAgc2NhbGVfZmlsbF92aXJpZGlzX2ModHJhbnMgPSAibG9nIiwgZGlyZWN0aW9uID0gLTEpICsNCiMgICAjc2NhbGVfY29sb3JfdmlyaWRpc19jKHRyYW5zID0gImxvZyIpICsNCiMgICBnZ3RoZW1lczo6dGhlbWVfbWFwKCkNCg0KIyBjcm9wIGhleG9nZW5zIHRvIG91dGxpbmUgb2YgRW5nbGFuZCBhbmQgV2FsZXMNCmhleF9wb2x5Z29uc19FVyA8LSBoZXhfcG9seWdvbnNbY291bnRyeV9ib3VuZCwgXQ0KDQojIGhleF9wb2x5Z29uX0VXICU+JSANCiMgICBjb3VudChwZW9wbGVfd29fZ2FyKQ0KDQpnZ3Bsb3QoKSArDQogICNnZW9tX3NmKGRhdGEgPSBtYXBfYm91bmQpICsNCiAgI2dlb21fc2YoZGF0YSA9IHN0X2NlbnRyb2lkKG1zb2FfYm91bmQpLCBjb2xvdXIgPSAiZ3JleSIpICsNCiAgZ2VvbV9zZihkYXRhID0gaGV4X3BvbHlnb25zX0VXLCBhbHBoYSA9IDAuNSwgbWFwcGluZyA9IGFlcyhmaWxsID0gcGVvcGxlX3dvX2dhcikpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2ModHJhbnMgPSAibG9nIiwgZGlyZWN0aW9uID0gLTEpICsNCiAgdGhlbWVfdm9pZCgpDQogIA0KIyBoZXhfcG9seWdvbnMgJT4lIA0KIyAgIGZpbHRlcihwZW9wbGVfd29fZ2FyID09IDApDQojIA0KIyBwZW9wbGVfd29fZ2FyX3NwYXRpYWwgJT4lIA0KIyAgIGZpbHRlcihwZW9wbGVfd29fZ2FyID09IDApDQoNCiMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFNtb290aA0KIyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQoNCmBgYA0KDQo8aHR0cHM6Ly9wdWRkaW5nLmNvb2wvcHJvY2Vzcy9yZWdpb25hbF9zbW9vdGhpbmcvPg0KDQpgYGB7cn0NCmxpYnJhcnkoc3BkZXApDQoNCiMgY29udmVydCBnZW8tZGYgdG8gcGxhaW4gZGYNCmhleF9wb2x5Z29uc19FV19kZiA8LSBoZXhfcG9seWdvbnNfRVcgJT4lIA0KICBzdF9kcm9wX2dlb21ldHJ5KCkNCg0KIyBnZXQgY2VudHJvaWQgb2YgZWFjaCBoZXhhZ29uDQpoZXhfY2VudHJvaWRzIDwtIGhleF9wb2x5Z29uc19FVyAlPiUgDQogIG11dGF0ZShnZW9tZXRyeSA9IHN0X2NlbnRyb2lkKGdlb21ldHJ5KSkNCg0KIyBmaW5kIGsgbmVhcmVzdCBuZWlnaGJvcnMNCmtubjUgPC0ga25uMm5iKGtuZWFybmVpZ2goaGV4X2NlbnRyb2lkcywgayA9IDEwKSkNCmtubjUgPC0gaW5jbHVkZS5zZWxmKGtubjUpDQoNCiMgQ3JlYXRpbmcgdGhlIGxvY2FsRyBzdGF0aXN0aWMgZm9yIGVhY2ggb2YgY291bnRpZXMsIHdpdGggYSBrLW5lYXJlc3QgbmVpZ2hib3IgdmFsdWUgb2YgNSwgYW5kIHJvdW5kIHRoaXMgdG8gMyBkZWNpbWFsIHBsYWNlcw0KbG9jYWxHdmFsdWVzIDwtIGxvY2FsRyh4ID0gYXMubnVtZXJpYyhoZXhfcG9seWdvbnNfRVdfZGYkcGVvcGxlX3dvX2dhciksIGxpc3R3ID0gbmIybGlzdHcoa25uNSwgc3R5bGUgPSAiQiIpLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQpsb2NhbEd2YWx1ZXMgPC0gcm91bmQobG9jYWxHdmFsdWVzLDMpDQoNCiMgQ3JlYXRlIGEgbmV3IGRhdGEgZnJhbWUgdGhhdCBvbmx5IGluY2x1ZGVzIHRoZSBoZXhvZ29ucyBhbmQgdGhlIEcgc2NvcmVzDQpuZXdfZGYgPC0gaGV4X3BvbHlnb25zX0VXIA0KbmV3X2RmJHZhbHVlcyA8LSBsb2NhbEd2YWx1ZXMNCg0KbmV3X2RmICU+JSANCiAgZ2dwbG90KGFlcyh2YWx1ZXMgKyAxLjUpKSArDQogIGdlb21faGlzdG9ncmFtKCkNCg0Kc3VtKG5ld19kZiR2YWx1ZXMgPT0gMCkNCg0KZ2dwbG90KCkgKw0KICAjZ2VvbV9zZihkYXRhID0gbWFwX2JvdW5kKSArDQogICNnZW9tX3NmKGRhdGEgPSBzdF9jZW50cm9pZChtc29hX2JvdW5kKSwgY29sb3VyID0gImdyZXkiKSArDQogIGdlb21fc2YoZGF0YSA9IG5ld19kZiwgbWFwcGluZyA9IGFlcyhmaWxsID0gdmFsdWVzICsgMS41LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gdmFsdWVzICsgMS41KSkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYyh0cmFucyA9ICJsb2ciLCBvcHRpb24gPSAibWFnbWEiLCBiZWdpbiA9IDApICsNCiAgI3NjYWxlX2NvbG91cl92aXJpZGlzX2ModHJhbnMgPSAibG9nIiwgb3B0aW9uID0gIm1hZ21hIiwgYmVnaW4gPSAwKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KZ2dzYXZlKCJnYXJkZW5fcGxvdC5zdmciKQ0KYGBgDQoNCkxvb2tpbmcgYXQgY2hhbmdlIGluIHBhcmsgdXNhZ2UgKGluIHR3byBwZXJpb2RzIGluIDIwMjApIHZzIGdhcmRlbiBhY2Nlc3MuDQoNCltVc2FnZSBkYXRhIGZyb20gR29vZ2xlIHZpYSBPTlNdKGh0dHBzOi8vd3d3Lm9ucy5nb3YudWsvZWNvbm9teS9lbnZpcm9ubWVudGFsYWNjb3VudHMvYXJ0aWNsZXMvaG93aGFzbG9ja2Rvd25jaGFuZ2Vkb3VycmVsYXRpb25zaGlwd2l0aG5hdHVyZS8yMDIxLTA0LTI2KQ0KDQpgYGB7cn0NCg0KIyByZWFkIGluIEdvb2dsZS9PTlMgcGFyayB1c2FnZSBkYXRhDQpwYXJrX3VzZWFnZSA8LSByZWFkX3hsc3goImRhdGEvY2hhbmdlX2luX3BhcmtzX3Zpc2l0c18yMDIwX0xBLnhsc3giLCBza2lwID0gNikgJT4lDQogIA0KICAjIGFwcGx5IGNvbnNpc3RlbnQgbmFtaW5nIHN0eWxlDQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lIA0KICANCiAgIyBzaG9ydGVuIG5hbWVzIGZvciByZWFkaWJsaXR5DQogIHJlbmFtZShwZXJjX2NoX3BhcmtzX3NwcmluZ19sb2NrID0gcGVyY2VudF9jaGFuZ2VfaW5fdmlzaXRzX3RvX2FuZF90aW1lX3NwZW50X2luX3BhcmtzX2R1cmluZ19zcHJpbmdfMjAyMF9sb2NrZG93biwNCiAgICAgICAgIHBlcmNfY2hfcGFya19zdW1tZXIgPSBwZXJjZW50X2NoYW5nZV9pbl92aXNpdHNfdG9fYW5kX3RpbWVfc3BlbnRfaW5fcGFya3NfZHVyaW5nX2p1bHlfYW5kX2F1Z3VzdF8yMDIwLA0KICAgICAgICAgbGFkX2NvZGUgPSBhcmVhX2NvZGVzLA0KICAgICAgICAgbGFkX25hbWUgPSBhcmVhX25hbWVzKQ0KDQpwYXJrX3VzZWFnZQ0KDQojIHJlYWQgaW4gdXJiYW4gLyBydXJhbCBjbGFzc2lmaWNhdGlvbg0KdXJiX3J1cl9jbGFzcyA8LSByZWFkX2NzdigiZGF0YS9SdXJhbF9VcmJhbl9DbGFzc2lmaWNhdGlvbl8oMjAwMSlfZm9yX01TT0FzX2luX0VuZ2xhbmRfYW5kX1dhbGVzL1JVQ19NU09BXzIwMDFfRVdfTFUuY3N2IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JSANCiAgc2VsZWN0KGxhZF9jb2RlID0gbGFkMDFjZCwgbGFkX25hbWUgPSBsYWQwMW5tLCANCiAgICAgICAgIGNsYXNzX25hbWUgPSBtb3JwaG9sb2d5X25hbWUsIA0KICAgICAgICAgY2xhc3NfY29kZSA9IG1vcnBob2xvZ3lfY29kZSkNCg0KIyBwcm9jZXNzIHVyYmFuIC8gcnVyYWwgY2xhc3NpZmljYXRpb24gDQp1cmJfcnVyX0xBRCA8LSB1cmJfcnVyX2NsYXNzICU+JSANCiAgbXV0YXRlKGlzX3VyYmFuID0gY2xhc3NfY29kZSA9PSAxKSAlPiUgDQogIGdyb3VwX2J5KGxhZF9uYW1lKSAlPiUgDQogIHN1bW1hcmlzZShuX3RvdCA9IG4oKSwNCiAgICAgICAgICAgIG5fdXJiYW4gPSBzdW0oaXNfdXJiYW4pLA0KICAgICAgICAgICAgcHJvcF91cmJhbiA9IG5fdXJiYW4gLyBuX3RvdCkgJT4lIA0KICBtdXRhdGUoaXNfdXJiYW5fTEFEID0gcHJvcF91cmJhbiA+IDAuNzUpDQoNCiMgcmVhZCBpbiBMQSBib3VuZGFyaWVzDQpMQV9ib3VuZHMgPC0gc3RfcmVhZCgiZGF0YS9MQV9ib3VuZC9Mb2NhbF9BdXRob3JpdHlfRGlzdHJpY3RzXyhEZWNlbWJlcl8yMDE5KV9Cb3VuZGFyaWVzX1VLX0JGQy5zaHAiKSAlPiUgDQogIHJlbmFtZShsYWRfY29kZSA9IGxhZDE5Y2QsDQogICAgICAgICBsYWRfbmFtZSA9IGxhZDE5bm0gKQ0KDQpMQV9ib3VuZHMNCg0KIyBhZ2dyZWdhdGUgZ2FyZGVucyBkYXRhIHRvIExBRCBzY2FsZQ0KZ2FyZGVuc19MQUQgPC0gZ2FyZGVucyAlPiUgDQogIG11dGF0ZShhZF93b19nYXIgPSByb3VuZChhZF9jb3VudCAqICgxIC0gcGVyY19vZl9hZGVzX3dpdGhfZ2FyKSkpICU+JSANCiAgZ3JvdXBfYnkobGFkX2NvZGUsIGxhZF9uYW1lKSAlPiUgDQogIHN1bW1hcmlzZShhZF9jb3VudCA9IHN1bShhZF9jb3VudCksDQogICAgICAgICAgICBhZF93b19nYXIgPSBzdW0oYWRfd29fZ2FyKSwNCiAgICAgICAgICAgIHByb3BfYWRfd29fZ2FyID0gYWRfd29fZ2FyIC8gYWRfY291bnQpIA0KDQojIGpvaW4gZGF0IHNldHMNCmdhcl9wYXJrX3VzZSA8LSBwYXJrX3VzZWFnZSAlPiUgDQogIGxlZnRfam9pbihnYXJkZW5zX0xBRCkgJT4lIA0KICBsZWZ0X2pvaW4odXJiX3J1cl9MQUQpDQoNCiMgY2hlY2sgZm9yIE5BIGNyZWF0ZWQgZHVyaW5nIGpvaW5pbmcNCmdhcl9wYXJrX3VzZSAlPiUgDQogIHNraW1yOjpza2ltKCkNCg0KZ2FyX3BhcmtfdXNlICU+JSANCiAgZmlsdGVyKGlzLm5hKGlzX3VyYmFuX0xBRCkpDQoNCiMgcHJvZHVjZSBwbG90DQpnZ3Bsb3QoZ2FyX3BhcmtfdXNlLCBhZXMocHJvcF9hZF93b19nYXIsIHBlcmNfY2hfcGFya3Nfc3ByaW5nX2xvY2ssDQogICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gaXNfdXJiYW5fTEFEKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArDQogICNzY2FsZV94X2xvZzEwKCkgKw0KICB4bGltKGMoMCwwLjUpKSArDQogIGZhY2V0X3dyYXAofmlzX3VyYmFuX0xBRCkNCg0KZ2dwbG90KGdhcl9wYXJrX3VzZSwgYWVzKHByb3BfYWRfd29fZ2FyLCBwZXJjX2NoX3Bhcmtfc3VtbWVyKSkgKw0KICBnZW9tX3BvaW50KCkNCg0KbW9kXzEgPC0gcnN0YW5hcm06OnN0YW5fZ2xtKHBlcmNfY2hfcGFya3Nfc3ByaW5nX2xvY2sgfiBwcm9wX2FkX3dvX2dhciwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGZpbHRlcihnYXJfcGFya191c2UsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcF9hZF93b19nYXIgPCAwLjIgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc191cmJhbl9MQUQgPT0gVFJVRSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2ggPSAwKQ0KDQptZWRpYW4ocnN0YW5hcm06OmJheWVzX1IyKG1vZF8xKSkNCmBgYA0KDQpgYGB7cn0NCmZvZV9ncmVlbl9zcGFjZSA8LSByZWFkX3hsc3goImRhdGEvKEZPRSkgR3JlZW4gU3BhY2UgQ29uc29saWRhdGVkIERhdGEgLSBFbmdsYW5kIC0gVmVyc2lvbiAyLjEueGxzeCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0ID0gIkxvY2FsIEF1dGhvcml0aWVzIFYyLjEiKSAlPiUgDQogIGNsZWFuX25hbWVzKCkgJT4lIA0KICBzZWxlY3QobGFkX2NvZGUgPSBsYV9jb2RlLCANCiAgICAgICAgIGxhZF9uYW1lID0gbGFfbmFtZSwNCiAgICAgICAgIHBvcCA9IHRvdGFsX3BvcF9mcm9tX2V0aG5pY2l0eV9kYXRhLA0KICAgICAgICAgYmFtZV9wb3AsDQogICAgICAgICBpbmNvbWVfaW5kZXgsDQogICAgICAgICBwY250X3BvcF93aXRoX2dvX3NwYWNlX2FjY2VzcywNCiAgICAgICAgIGdyZWVuX3NwYWNlX2FyZWFfcGVyX2NhcGl0YSkNCg0KIyBqb2luIGZvZSBkYXRhIHRvIGV4aXN0aW5nIGRhdGENCmdhcl9wYXJrX3VzZV9mb2UgPC0gZ2FyX3BhcmtfdXNlICU+JSANCiAgbGVmdF9qb2luKGZvZV9ncmVlbl9zcGFjZSkNCg0KIyBjaGVjayBOQXMgY3JlYXRlZCBieSBqb2luaW5nDQpza2ltcjo6c2tpbShnYXJfcGFya191c2VfZm9lKQ0KZ2FyX3BhcmtfdXNlX2ZvZSAlPiUgDQogIGZpbHRlcihpcy5uYShwb3ApKSAgIyBhbG1vc3QgYWxsIFNjb3RsYW5kIGFuZCBXYWxlcyANCiAgICAgICAgICAgICAgICAgICAgICAjIChhcyBleHBlY3RlZCBhcyBGT0UgaXMgRW5nbGFuZCBvbmx5KQ0KDQoNCmdhcl9wYXJrX3VzZV9mb2VfZW5nIDwtIGdhcl9wYXJrX3VzZV9mb2UgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHBvcCkpICU+JSANCiAgbXV0YXRlKHBlcmNfY2hfcGFya19zdW1tZXIgPSBuYV9pZihwZXJjX2NoX3Bhcmtfc3VtbWVyLCAiTm8gZGF0YSIpLA0KICAgICAgICAgcGVyY19jaF9wYXJrX3N1bW1lciA9IGFzLm51bWVyaWMocGVyY19jaF9wYXJrX3N1bW1lciksDQogICAgICAgICBwcm9wX2JhbWVfcG9wID0gYmFtZV9wb3AgLyBwb3ApDQoNCmdhcl9wYXJrX3VzZV9mb2VfZW5nDQoNCmdhcl9wYXJrX3VzZV9mb2VfZW5nX21vZF9pbiA8LSBnYXJfcGFya191c2VfZm9lX2VuZyAlPiUgDQogIHNlbGVjdCgtbGFkX2NvZGUsIC1sYWRfbmFtZSwgLXBvcCwgLWJhbWVfcG9wLA0KICAgICAgICAgLW5fdG90LCAtbl91cmJhbiwgLWlzX3VyYmFuX0xBRCwgLWFkX2NvdW50LC1hZF93b19nYXIsDQogICAgICAgICAtcGVyY19jaF9wYXJrX3N1bW1lciwgLXBjbnRfcG9wX3dpdGhfZ29fc3BhY2VfYWNjZXNzLCAtZ3JlZW5fc3BhY2VfYXJlYV9wZXJfY2FwaXRhKQ0KICANCg0KbW9kXzIgPC0gcnN0YW5hcm06OnN0YW5fZ2xtKHBlcmNfY2hfcGFya3Nfc3ByaW5nX2xvY2sgfiAuLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2FyX3BhcmtfdXNlX2ZvZV9lbmdfbW9kX2luLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoID0gMCkNCg0KbWVkaWFuKHJzdGFuYXJtOjpiYXllc19SMihtb2RfMikpDQoNCm1vZF8zIDwtIHJzdGFuYXJtOjpzdGFuX2dsbShwZXJjX2NoX3BhcmtzX3NwcmluZ19sb2NrIH4gcHJvcF9hZF93b19nYXIgKyBwcm9wX3VyYmFuICsgaW5jb21lX2luZGV4ICsgcHJvcF9iYW1lX3BvcCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdhcl9wYXJrX3VzZV9mb2VfZW5nX21vZF9pbiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaCA9IDApDQoNCm1lZGlhbihyc3RhbmFybTo6YmF5ZXNfUjIobW9kXzMpKQ0KDQpnZ3Bsb3QoZ2FyX3BhcmtfdXNlX2ZvZV9lbmdfbW9kX2luLCBhZXMocHJvcF9iYW1lX3BvcCwgcGVyY19jaF9wYXJrc19zcHJpbmdfbG9jaykpICsNCiAgZ2VvbV9wb2ludCgpDQoNCnAgPC0gZ2dwbG90KGZpbHRlcihnYXJfcGFya191c2VfZm9lX2VuZywgcHJvcF91cmJhbiA+IDAuOCksIA0KICAgICAgIGFlcyhwcm9wX2FkX3dvX2dhciwgcGVyY19jaF9wYXJrc19zcHJpbmdfbG9jaywgDQogICAgICAgICAgIGNvbG91ciA9IHByb3BfYmFtZV9wb3AsIA0KICAgICAgICAgICBzaXplID0gZ3JlZW5fc3BhY2VfYXJlYV9wZXJfY2FwaXRhLA0KICAgICAgICAgICBsYWJlbCA9IGxhZF9uYW1lKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArDQogIHNjYWxlX2NvbG91cl92aXJpZGlzX2MoKSArDQogIHhsaW0oYygwLC41KSkNCiAgI3NjYWxlX3hfbG9nMTAoKQ0KDQpwbG90bHk6OmdncGxvdGx5KHApDQoNCnAyIDwtIGdncGxvdChkYXRhID0gZmlsdGVyKGdhcl9wYXJrX3VzZV9mb2VfZW5nLCBwcm9wX3VyYmFuID4gMC44KSwNCiAgICAgICAgICAgICBhZXMocHJvcF9iYW1lX3BvcCwgcHJvcF9hZF93b19nYXIpKSArDQogIGdlb21fcG9pbnQoKSArDQogIHlsaW0oYygwLDAuNSkpDQoNCnAyDQoNCnAzIDwtIGdncGxvdChmaWx0ZXIoZ2FyX3BhcmtfdXNlX2ZvZV9lbmcsIHByb3BfdXJiYW4gPiAwLjgpLCANCiAgICAgICBhZXMocHJvcF9iYW1lX3BvcCwgcGVyY19jaF9wYXJrc19zcHJpbmdfbG9jaywgDQogICAgICAgICAgIGNvbG91ciA9IHByb3BfYWRfd29fZ2FyLCANCiAgICAgICAgICAgc2l6ZSA9IGdyZWVuX3NwYWNlX2FyZWFfcGVyX2NhcGl0YSwNCiAgICAgICAgICAgbGFiZWwgPSBsYWRfbmFtZSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICBzY2FsZV9jb2xvdXJfdmlyaWRpc19jKGRpcmVjdGlvbiA9IC0xLCB0cmFucyA9ICJsb2ciLCBlbmQgPSAwLjkpICsNCiAgeGxpbShjKDAsLjUpKQ0KDQpwMw0KcGxvdGx5OjpnZ3Bsb3RseShwMykNCg0KcDQgPC0gZ2dwbG90KGZpbHRlcihnYXJfcGFya191c2VfZm9lX2VuZywgcHJvcF91cmJhbiA+IDAuOCksIA0KICAgICAgIGFlcyhwZXJjX2NoX3BhcmtzX3NwcmluZ19sb2NrLCBwZXJjX2NoX3Bhcmtfc3VtbWVyLA0KICAgICAgICAgICBjb2xvdXIgPSBwcm9wX2FkX3dvX2dhciwNCiAgICAgICAgICAgc2l6ZSA9IGdyZWVuX3NwYWNlX2FyZWFfcGVyX2NhcGl0YSwNCiAgICAgICAgICAgbGFiZWwgPSBsYWRfbmFtZSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkrDQogIHNjYWxlX2NvbG91cl92aXJpZGlzX2MoZGlyZWN0aW9uID0gLTEsIHRyYW5zID0gImxvZyIsIGVuZCA9IDAuOSkNCg0KcDQNCg0KcGxvdGx5OjpnZ3Bsb3RseShwNCkNCmBgYA0KDQpNYWpvciBjaXRpZXMNCg0KYGBge3J9DQpsYV9yZWdpb25fbG9va3VwIDwtIGdhcmRlbnMgJT4lDQogIHNlbGVjdChyZWdpb25fY29kZTpsYWRfbmFtZSkgJT4lIA0KICBkaXN0aW5jdCgpDQoNCmxvbmRvbiA8LSBnYXJfcGFya191c2VfZm9lX2VuZyAlPiUgDQogIGxlZnRfam9pbihsYV9yZWdpb25fbG9va3VwKSAlPiUgDQogIGZpbHRlcihyZWdpb25fbmFtZSA9PSAiTG9uZG9uIikNCg0Kb3RoZXJfYmlnX2NpdGllcyA8LSBnYXJfcGFya191c2VfZm9lX2VuZyAlPiUgDQogIGxlZnRfam9pbihsYV9yZWdpb25fbG9va3VwKSAlPiUgDQogIGZpbHRlcihyZWdpb25fbmFtZSAhPSAiTG9uZG9uIikgJT4lIA0KICBmaWx0ZXIocHJvcF91cmJhbiA+PSAwLjgpICU+JSANCiAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gcG9wLCBuID0gMjkpDQoNCnRoaXJ0eV9iaWdnZXN0X2NpdGllcyA8LSBsb25kb24gJT4lIA0KICBiaW5kX3Jvd3Mob3RoZXJfYmlnX2NpdGllcykgJT4lIA0KICBtdXRhdGUoaXNfbG9uZG9uID0gcmVnaW9uX25hbWUgPT0gIkxvbmRvbiIsDQogICAgICAgICBnc19wY19iaW4gPSBjdXQoZ3JlZW5fc3BhY2VfYXJlYV9wZXJfY2FwaXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoMCwgMTAsIDI1LCA1MCwgSW5mKSksDQogICAgICAgICBwcm9wX2FkX3dpdGhfZ2FyID0gMSAtIHByb3BfYWRfd29fZ2FyKQ0KDQpjb2xvdXJzIDwtIGMoImdyZXkzMCIsICJncmV5NzAiLCAicGFsZWdyZWVuIiwgInBhbGVncmVlbjQiKQ0KDQpwIDwtIGdncGxvdCh0aGlydHlfYmlnZ2VzdF9jaXRpZXMsIA0KICAgICAgIGFlcyhwcm9wX2FkX3dpdGhfZ2FyLCBwZXJjX2NoX3BhcmtzX3NwcmluZ19sb2NrLCANCiAgICAgICAgICAgY29sb3VyID0gZ3NfcGNfYmluLCANCiAgICAgICAgICAgc2l6ZSA9IGdzX3BjX2JpbiwNCiAgICAgICAgICAgbGFiZWwgPSBsYWRfbmFtZSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGNvbG91cnMpICsNCiAgI3NjYWxlX2NvbG91cl92aXJpZGlzX2MoKSArDQogICNzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93ID0gImdyZXkzMCIsIGhpZ2ggPSAiZ3JlZW4iKSArDQogIHhsaW0oYygwLjUsMSkpICsNCiAgZmFjZXRfd3JhcCh+aXNfbG9uZG9uKQ0KICAjc2NhbGVfeF9sb2cxMCgpDQoNCnBsb3RseTo6Z2dwbG90bHkocCkNCg0KZ2dwbG90KHRoaXJ0eV9iaWdnZXN0X2NpdGllcykgKw0KICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKGdyZWVuX3NwYWNlX2FyZWFfcGVyX2NhcGl0YSkpDQoNCnA0IDwtIGdncGxvdCh0aGlydHlfYmlnZ2VzdF9jaXRpZXMsIA0KICAgICAgIGFlcyhwZXJjX2NoX3BhcmtzX3NwcmluZ19sb2NrLCBwZXJjX2NoX3Bhcmtfc3VtbWVyLA0KICAgICAgICAgICBjb2xvdXIgPSBncmVlbl9zcGFjZV9hcmVhX3Blcl9jYXBpdGEsDQogICAgICAgICAgIHNpemUgPSBncmVlbl9zcGFjZV9hcmVhX3Blcl9jYXBpdGEsDQogICAgICAgICAgIGxhYmVsID0gbGFkX25hbWUpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpKw0KICBzY2FsZV9jb2xvdXJfdmlyaWRpc19jKGVuZCA9IDAuOSkgKw0KICBmYWNldF93cmFwKH5pc19sb25kb24pDQoNCnA0DQoNCnBsb3RseTo6Z2dwbG90bHkocDQpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KG5uZ2VvKQ0KDQojIGlkZW50aWZ5IG5lYXJlc3QgbmVpZ2hib3VycyBhbmQgY29udmVydCBhbG9naXRobW4gb3V0cHV0IHRvIGEgZGF0YWZyYW1lDQpuZWlnaF9oZXggPC0gc3Rfbm4oaGV4X3BvbHlnb25zX0VXLCBoZXhfcG9seWdvbnNfRVcsIGsgPSA2KQ0KbmVpZ2hfaGV4IDwtIGRhdGEuZnJhbWUobWF0cml4KHVubGlzdChuZWlnaF9oZXgpLCBuY29sID0gbWF4KGxlbmd0aHMobmVpZ2hfaGV4KSksIGJ5cm93ID0gVFJVRSkpDQoNCmxvb2tfdXBfcGVvcF93b19nYXIgPC0gZnVuY3Rpb24oZGYsIHJvd19udW0pew0KICBkZltyb3dfbnVtLCAncGVvcGxlX3dvX2dhciddICU+JSANCiAgICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lIA0KICAgIHBsdWNrKCdwZW9wbGVfd29fZ2FyJykNCn0NCg0KDQojIHJlc2V0IHJvdyBudW1iZXJzIHRvIGF2b2lkIGNvbmZ1c2lvbiB3aGVuIGFkZGluZyBuZWFyZXN0IG5laWdoYm9ycw0Kcm93Lm5hbWVzKGhleF9wb2x5Z29uX0VXKSA8LSBOVUxMDQoNCiMgYWRkIG5lYXJlc3QgbmVpZ2hib3JzIHRvIHBvbHlnb24NCmhleF9wb2x5Z29uX0VXX25uIDwtIGhleF9wb2x5Z29uX0VXICU+JSANCiAgYmluZF9jb2xzKG5laWdoX2hleCkNCg0KDQprbm5faW50ZXJwb2xhdGlvbiA8LSBoZXhfcG9seWdvbl9FV19ubiAlPiUgDQogIG11dGF0ZShhY3Jvc3MoWDE6WDYsIH4gbG9va191cF9wZW9wX3dvX2dhcihoZXhfcG9seWdvbl9FV19ubiwgLikpKSAlPiUgDQogIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUgDQogIG11dGF0ZShrbm5fYXZlID0gcm91bmQocm93TWVhbnMoc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJYIikpKSkpICU+JSANCiAgcHVsbChrbm5fYXZlKQ0KICANCmhleF9wb2x5Z29uX0VXX25uICU+JSANCiAgYmluZF9jb2xzKGtubl9pbnRlcnBvbGF0aW9uKQ0KDQpoZXhfcG9seWdvbl9pbnRlcnBvbGF0aW9uDQpgYGANCg==